﻿using LibNiconico.NiconicoApi.Internal;
using LibNiconico.NiconicoApi.Lives.Constant;
using LibNiconico.NiconicoApi.Lives.PublishStatus;
using LibNiconico.NiconicoApi.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LibNiconico.NiconicoApi.Lives.Broadcast
{
    /// <summary>
    /// ニコ生放送配信APIヘルパー
    /// </summary>
    public class NicoLiveBroadcastApiHelper : NicoApiHelperBase
    {
        internal NicoLiveBroadcastApiHelper(NiconicoAuth auth, NiconicoApiInfoGetCreateInfo careateInfo):base(auth,careateInfo)
        {

        }

        /// <summary>
        /// 生放送可能な情報を取得
        /// </summary>
        /// <returns></returns>
        public async Task<NicoLiveBroadcastableInfoGetResponse> GetBroadcastableInfoAsync()
        {
            using (var api = new NiconicoInfoGetApiHtmlImpl(NicoLiveConstant.NICOLIVE_URL, CreateMostLoginApiHttpClient()))
            {
                return NicoLiveBroadcastableInfoGetResponse.Parse((await api.GetAsync(new NicoLiveBroadcastableInfoGetRequestQueryInfo()).ConfigureAwait(false)).Content);
            }
        }

        /// <summary>
        /// 放送枠を作成
        /// </summary>
        /// <param name="queryInfo"></param>
        /// <returns></returns>
        public async Task<NicoLiveBroadcastCreateResponse> CreateLiveBroadcastAsync(NicoLiveBroadcastCreateQueryInfo queryInfo)
        {
            if (queryInfo == null) throw new ArgumentNullException();

            var confirmQueryInfo = await openCreateLiveBroadcastConfirmRequestAsync(queryInfo).ConfigureAwait(false);

            if (confirmQueryInfo.FormData.Count <= 0)
            {

                return new NicoLiveBroadcastCreateResponse(NicoLiveBroadcastResultCode.CreateBroadcastFailed, confirmQueryInfo.ErrorMessage);
            }


            return await openCreateLiveBroadcastAccomplished(confirmQueryInfo).ConfigureAwait(false);
        }


        /// <summary>
        /// 放送枠待機情報取得
        /// </summary>
        /// <param name="liveInfo"></param>
        /// <returns></returns>
        public async Task<NicoLiveBroadcastWaitInfoResponse> GetWaitInfoAsync(NicoLiveBroadcastableLiveInfo liveInfo)
        {
            if (liveInfo == null) throw new ArgumentNullException();

            return await this.GetWaitInfoAsync(new NicoLiveBroadcastWaitInfoQueryInfo(liveInfo.LiveId)).ConfigureAwait(false);
        }


        internal async Task<NicoLiveBroadcastWaitInfoResponse> GetWaitInfoAsync(NicoLiveBroadcastWaitInfoQueryInfo queryInfo)
        {
            using (var api = new NiconicoInfoGetApiXmlImpl(NicoLiveConstant.NICOLIVE_URL, CreateMostLoginApiHttpClient()))
            {
                return NicoLiveBroadcastWaitInfoResponse.Parse((await api.GetAsync(queryInfo).ConfigureAwait(false)).Content);
            }
        }

        /// <summary>
        /// 放送枠作成確認画面を開く
        /// </summary>
        /// <param name="queryInfo"></param>
        /// <returns></returns>
        private async Task<NicoLiveBroadcastCreateConfirmQueryInfo> openCreateLiveBroadcastConfirmRequestAsync(NicoLiveBroadcastCreateQueryInfo queryInfo)
        {
            using (var api = new NiconicoInfoGetApiHtmlImpl(NicoLiveConstant.NICOLIVE_URL, CreateMostLoginApiHttpClient()))
            {
                return NicoLiveBroadcastCreateConfirmQueryInfo.CreateFrom((await api.PostAsync(queryInfo).ConfigureAwait(false)).Content);
            }
        }

        private async Task<NicoLiveBroadcastCreateResponse> openCreateLiveBroadcastAccomplished(NicoLiveBroadcastCreateConfirmQueryInfo queryInfo)
        {
            if (queryInfo == null) throw new ArgumentNullException();

            using (var api = new NiconicoInfoGetApiHtmlImpl(NicoLiveConstant.NICOLIVE_URL, CreateMostLoginApiHttpClient()))
            {
                var createResponse = NicoLiveBroadcastCreateResponse.Parse(await api.PostAsync(queryInfo).ConfigureAwait(false));

                if (createResponse.ResultCode == NicoLiveBroadcastResultCode.QueueStart)
                {
                    queryInfo.FormData.Add("is_wait", "wait");
                    return await openCreateLiveBroadcastAccomplished(queryInfo).ConfigureAwait(false);
                }

                return createResponse;
            }

        }


        /// <summary>
        /// 指定した生放送IDを強制開始
        /// </summary>
        /// <param name="liveInfo"></param>
        /// <returns></returns>
        public async Task<NicoLiveBroadcastStartResponse> StartBroadcastAsync(NicoLiveBroadcastableLiveInfo liveInfo)
        {
            if (liveInfo == null) throw new ArgumentNullException();

            var publishStatus = await getPublishStatusAsync(new NicoLiveGetPublishStatusQueryInfo(liveInfo.LiveId)).ConfigureAwait(false);

            if (string.IsNullOrEmpty(publishStatus.PublishStatus.Token))
            {
                return new NicoLiveBroadcastStartResponse(false);
            }

            return await StartBroadcastAsync(new NicoLiveBroadcastStartQueryInfo(liveInfo.LiveId, publishStatus.PublishStatus.Token)).ConfigureAwait(false);
        }


        internal async Task<NicoLiveBroadcastStartResponse> StartBroadcastAsync(NicoLiveBroadcastStartQueryInfo queryInfo)
        {
            using (var api = new NiconicoInfoGetApiXmlImpl(NicoLiveConstant.NICOLIVE_URL, CreateMostLoginApiHttpClient()))
            {
                return NicoLiveBroadcastStartResponse.Parse((await api.GetAsync(queryInfo).ConfigureAwait(false)).Content);
            }
        }


        /// <summary>
        /// 自分が放送している放送を停止
        /// </summary>
        /// <param name="liveId"></param>
        /// <returns></returns>
        public async Task<NicoLiveBroadcastStopResponse> StopBroadcastAsync(string liveId)
        {
            if (liveId == null) throw new ArgumentNullException();
            var publishStatus = await getPublishStatusAsync(new NicoLiveGetPublishStatusQueryInfo(liveId)).ConfigureAwait(false);

            if (string.IsNullOrEmpty(publishStatus.PublishStatus.Token))
            {
                return new NicoLiveBroadcastStopResponse(false);
            }


            return await StopBroadcastAsync(new NicoLiveBroadcastStopQueryInfo(liveId, publishStatus.PublishStatus.Token)).ConfigureAwait(false);

        }

        internal async Task<NicoLiveBroadcastStopResponse> StopBroadcastAsync(NicoLiveBroadcastStopQueryInfo queryInfo)
        {
            using(var api = new NiconicoInfoGetApiXmlImpl(NicoLiveConstant.NICOLIVE_URL,CreateMostLoginApiHttpClient()))
            {
                return NicoLiveBroadcastStopResponse.Parse((await api.GetAsync(queryInfo).ConfigureAwait(false)).Content);
            }
        }


        private async Task<NicoLiveGetPublishStatusResponse> getPublishStatusAsync(NicoLiveGetPublishStatusQueryInfo queryInfo)
        {
            using (NiconicoInfoGetApiXmlImpl api = new NiconicoInfoGetApiXmlImpl(NicoLiveConstant.NICOLIVE_URL, CreateMostLoginApiHttpClient()))
            {
                return NicoLiveGetPublishStatusResponse.Parse((await api.GetAsync(queryInfo).ConfigureAwait(false)).Content);
            }
        }
    }
}
